package com.ctshk.rpc.cms.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ctshk.common.dto.Result;
import com.ctshk.common.enums.IsDeletedCode;
import com.ctshk.common.enums.SystemError;
import com.ctshk.common.model.PageResponse;
import com.ctshk.common.model.TokenUser;
import com.ctshk.common.utils.EntityUtil;
import com.ctshk.common.utils.redis.KeyUtil;
import com.ctshk.rpc.cms.constant.CmsConstant;
import com.ctshk.rpc.cms.dto.NoticeDTO;
import com.ctshk.rpc.cms.entity.Notice;
import com.ctshk.rpc.cms.entity.NoticePosition;
import com.ctshk.rpc.cms.mapper.NoticeMapper;
import com.ctshk.rpc.cms.mapper.NoticePositionMapper;
import com.ctshk.rpc.cms.req.*;
import com.ctshk.rpc.cms.service.INoticeService;
import com.ctshk.rpc.system.dto.UserDTO;
import com.ctshk.rpc.system.service.ISysUserService;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 公告管理 服务实现类
 * </p>
 *
 * @author LiZhiming
 * @since 2021-04-23
 */
@DubboService
public class NoticeServiceImpl extends ServiceImpl<NoticeMapper, Notice> implements INoticeService {

    @DubboReference
    private ISysUserService sysUserService;

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Autowired
    private NoticePositionMapper noticePositionMapper;

    @Override
    public Result insert(NoticeAddReq req, TokenUser tu) {
        Notice notice = EntityUtil.copy(req, Notice.class);
        LocalDateTime now = LocalDateTime.now();
        Long id = IdWorker.getId();
        notice.setCreateId(tu.getId());
        notice.setGmtCreate(now);
        notice.setId(id);
        notice.setIsDeleted(IsDeletedCode.NO.getCode());
        int insert = baseMapper.insert(notice);
        if (insert > 0) {
            //做了修改操作如果存在这个缓存就清除缓存
            Set<String> keysRecommend = redisTemplate.keys(KeyUtil.genLikeKey(CmsConstant.CMS_NOTICE_REDIS_KEY));
            if (CollUtil.isNotEmpty(keysRecommend)) {
                redisTemplate.delete(keysRecommend);
            }
            return Result.success(id);
        }
        return Result.failed(SystemError.CMS_23000);
    }

    @Override
    public Result<NoticeDTO> queryById(String noticeId) {
        NoticeDTO b = null;
        QueryWrapper<Notice> qw = new QueryWrapper<>();
        qw.lambda().eq(Notice::getIsDeleted, IsDeletedCode.NO.getCode())
                .eq(Notice::getId, noticeId);
        Notice notice = baseMapper.selectOne(qw);
        if (notice != null) {
            b = EntityUtil.copy(notice, NoticeDTO.class);
        }
        return Result.success(b);
    }

    @Override
    public PageResponse<NoticeDTO> queryList(NoticeQueryReq req) {
        List<Long> npIds = new ArrayList<>();
        QueryWrapper<NoticePosition> qwnp = new QueryWrapper<>();
        qwnp.lambda().eq(req.getNoticeType() != null, NoticePosition::getNoticeType, req.getNoticeType())
                .eq(NoticePosition::getIsDeleted, IsDeletedCode.NO.getCode());
        List<NoticePosition> noticePositions = noticePositionMapper.selectList(qwnp);
        Map<Long, NoticePosition> map = new HashMap<>();
        noticePositions.forEach(e -> map.put(e.getId(), e));
        if (noticePositions != null) {
            npIds = noticePositions.stream().map(e -> e.getId()).collect(Collectors.toList());
        }
        Page<Notice> page = new Page(req.getPageNo(), req.getPageSize());
        QueryWrapper<Notice> qw = new QueryWrapper();
        if (npIds != null && npIds.size() > 0) {
            qw.lambda().in(Notice::getNoticePositionId, npIds);
        }
        qw.lambda().eq(Notice::getIsDeleted, IsDeletedCode.NO.getCode())
                .eq(req.getNoticePositionId() != null, Notice::getNoticePositionId, req.getNoticePositionId())
                .eq(req.getNoticeName() != null, Notice::getNoticeName, req.getNoticeName())
                .eq(req.getStatus() != null, Notice::getStatus, req.getStatus())
                .eq(req.getNoticePositionName() != null, Notice::getNoticePositionName, req.getNoticePositionName())
                .orderByAsc(Notice::getSort, Notice::getGmtCreate);
        Page<Notice> noticePage = baseMapper.selectPage(page, qw);
        if (CollectionUtils.isNotEmpty(noticePage.getRecords())) {
            List<NoticeDTO> noticeDTOS = EntityUtil.copyList(noticePage.getRecords(), NoticeDTO.class);
            for (NoticeDTO item : noticeDTOS) {
                item.setNoticeType(map.get(item.getNoticePositionId()).getNoticeType());
                UserDTO userDTO = sysUserService.loadUserInfo(item.getCreateId(), 1);
                if (userDTO != null) {
                    item.setUserName(userDTO.getCnSurname() + userDTO.getCnName());
                }
            }
            return new PageResponse<>(noticeDTOS,
                    page.getCurrent() == 1, page.getTotal() <= (page.getCurrent() *
                    page.getSize()), page.getTotal(), page.getCurrent(), page.getSize());
        }
        return new PageResponse<>(null,
                page.getCurrent() == 1, page.getTotal() <= (page.getCurrent() *
                page.getSize()), page.getTotal(), page.getCurrent(), page.getSize());
    }

    @Override
    public List<NoticeDTO> queryListByCode(BannerPositionByTypeReq req) {
        ValueOperations ops = redisTemplate.opsForValue();
        NoticePosition bp = noticePositionMapper.selectOne(
                Wrappers.<NoticePosition>lambdaQuery().eq(NoticePosition::getNoticeCode, req.getCode())
                        .eq(NoticePosition::getIsDeleted, IsDeletedCode.NO.getCode())
        );
        if (bp == null) {
            return null;
        }
        //先取缓存不存在就重新查
        String opsBpl = (String) ops.get(CmsConstant.CMS_NOTICE_REDIS_KEY + bp.getId());
        if (StringUtils.isNotBlank(opsBpl)) {
            JSONArray ja = JSON.parseArray(opsBpl);
            List<NoticeDTO> list = ja.toJavaList(NoticeDTO.class);
            return list;
        }
        QueryWrapper<Notice> qw = new QueryWrapper();
        qw.lambda().eq(Notice::getIsDeleted, IsDeletedCode.NO.getCode())
                .eq(Notice::getNoticePositionId, bp.getId())
                .orderByAsc(Notice::getSort, Notice::getGmtCreate);
        List<Notice> notices = baseMapper.selectList(qw);
        if (notices != null && notices.size() > 0) {
            List<NoticeDTO> ns = EntityUtil.copyList(notices, NoticeDTO.class);
            if (ns != null && ns.size() > 0) {
                ops.set(CmsConstant.CMS_NOTICE_REDIS_KEY + bp.getId().toString(), JSON.toJSONString(ns));
            }
            return ns;
        }
        return null;
    }

    @Override
    public Result update(NoticeUpdateReq req, TokenUser tu) {
        LocalDateTime now = LocalDateTime.now();
        Notice copy = EntityUtil.copy(req, Notice.class);
        copy.setModifiedId(tu.getId());
        copy.setGmtModified(now);
        int i = baseMapper.updateById(copy);
        if (i > 0) {
            //做了修改操作如果存在这个缓存就清除缓存
            Set<String> keysRecommend = redisTemplate.keys(KeyUtil.genLikeKey(CmsConstant.CMS_NOTICE_REDIS_KEY));
            if (CollUtil.isNotEmpty(keysRecommend)) {
                redisTemplate.delete(keysRecommend);
            }
            return Result.success(req.getId());
        }
        return Result.failed(SystemError.CMS_23002);
    }

    @Override
    public Result updateStatusById(UpdateStatusReq req) {
        int i = baseMapper.updateStatusById(req.getId(), req.getStatus());
        if (i > 0) {
            Notice notice = baseMapper.selectById(req.getId());
            if (notice != null) {
                //做了修改操作如果存在这个缓存就清除缓存
                Set<String> keysRecommend = redisTemplate.keys(KeyUtil.genLikeKey(CmsConstant.CMS_NOTICE_REDIS_KEY));
                if (CollUtil.isNotEmpty(keysRecommend)) {
                    redisTemplate.delete(keysRecommend);
                }
            }
        }
        return Result.success(i);
    }
}
